// =============================================================================
// | 包: core                                                                 |
// | 模块: 数据库初始化                                                        |
// | 功能: 负责初始化数据库连接，配置GORM，支持读写分离                         |
// =============================================================================
package core

import (
	// 全局变量包 - 提供应用程序全局配置和共享变量
	"blog_server/global"          // 全局变量包 - 存储系统核心配置和共享数据
	// MySQL数据库驱动 - GORM框架的MySQL驱动实现
	"gorm.io/driver/mysql"        // MySQL驱动 - GORM框架连接MySQL数据库的驱动
	// GORM ORM框架 - 提供对象关系映射功能
	"gorm.io/gorm"                // GORM框架 - 提供高级ORM功能，简化数据库操作
	// 结构化日志库 - 用于记录应用程序运行时的日志信息
	"github.com/sirupsen/logrus"  // 日志库 - 提供结构化日志记录功能
	// 数据库读写分离插件 - GORM的插件，实现数据库读写分离功能
	"gorm.io/plugin/dbresolver"   // 读写分离插件 - GORM的官方插件，实现数据库读写分离
)

// =============================================================================
// | 函数: InitDB                                                             |
// | 参数: 无                                                                  |
// | 返回: @db - *gorm.DB - 初始化后的GORM数据库连接实例                      |
// | 功能: 创建数据库连接，配置GORM，并设置读写分离                             |
// | 说明: 初始化数据库连接池，配置ORM参数，并根据配置启用读写分离功能          |
// |----------------------------------------------------------------------------|
// | 流程:                                                                     |
// | 1. 获取数据库配置 - 从全局配置中读取读库和写库的连接信息                   |
// | 2. 创建数据库连接 - 使用读库配置初始化GORM连接实例                        |
// | 3. 配置GORM参数 - 禁用外键约束迁移，简化数据库结构变更                    |
// | 4. 检查连接状态 - 如连接失败则记录日志并终止程序                          |
// | 5. 配置读写分离 - 如果写库配置存在，则启用读写分离功能                    |
// | 6. 返回连接实例 - 将配置完成的数据库连接返回给调用者                      |
// =============================================================================
func InitDB() *gorm.DB {
	// 获取数据库配置
	// | 从全局配置中获取读库和写库的配置信息                                     |
	dc := global.Config.DB  // 读库配置 - 用于读取操作
	dc1 := global.Config.DB1 // 写库配置 - 用于写入操作

	// 初始化数据库连接（使用读库配置作为基础连接）
	// | 创建GORM DB实例，配置MySQL连接                                            |
	db, err := gorm.Open(mysql.Open(dc.DSN()), &gorm.Config{
		DisableForeignKeyConstraintWhenMigrating: true, // 不生成外键约束，简化迁移 - 避免迁移时的外键约束问题
	}) // 创建数据库连接并配置GORM参数

	// 检查数据库连接是否成功
	if err != nil {
		// 连接失败，记录致命错误并终止程序
		logrus.Fatalf("数据库连接失败 %s", err) // 数据库连接失败是致命错误，程序无法继续运行
	}
	
	// 记录连接成功信息
	// | 输出数据库连接成功的日志                                                 |
	logrus.Infof("数据库连接成功") // 记录信息日志，表明数据库连接初始化成功

	// 配置读写分离（如果写库配置不为空）
	// | 实现数据库读写分离，提升性能和扩展性                                     |
	if !dc1.Empty() {
		// 注册读写分离插件
		// | 配置主库（写库）和从库（读库）数据源                                   |
		err = db.Use(dbresolver.Register(dbresolver.Config{
			Sources:  []gorm.Dialector{mysql.Open(dc1.DSN())}, // 写库（主库）数据源 - 用于所有写入操作
			Replicas: []gorm.Dialector{mysql.Open(dc.DSN())},  // 读库（从库）数据源 - 用于所有读取操作
			Policy:   dbresolver.RandomPolicy{},               // 负载均衡策略：随机选择读库 - 均衡分布读请求
		})) // 注册并配置读写分离插件
		
		// 检查读写分离配置是否成功
		if err != nil {
			// 配置失败，记录致命错误并终止程序
			logrus.Fatalf("读写配置错误 %s", err) // 读写分离配置失败是致命错误，程序无法继续运行
		}
	}

	// 返回初始化完成的数据库连接实例
	// | 供全局变量和应用程序其他部分使用                                         |
	return db // 返回配置完成的GORM DB实例，用于后续数据库操作
}
